#include <jni.h>
#include <string>
#include "handler/YHHandler.h"
#include<thread>
#include <unistd.h>
#include <android/looper.h>
#include <sys/eventfd.h>

YHHandler *handler = nullptr;
YHHandler *mainHandler = nullptr;

jstring string2jstring(JNIEnv *env, const char *pat) {
    jclass strClass = (env)->FindClass("java/lang/String");
    jmethodID ctorID = (env)->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = (env)->NewByteArray(strlen(pat));
    (env)->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *) pat);
    jstring encoding = (env)->NewStringUTF("utf-8");
    jstring r = (jstring) (env)->NewObject(strClass, ctorID, bytes, encoding);
    env->DeleteLocalRef(strClass);
    env->DeleteLocalRef(bytes);
    env->DeleteLocalRef(encoding);
    return r;
}

char *jstring2string(JNIEnv *env, jstring jstr) {
    char *rtn = NULL;
    if (jstr == NULL) {
        jstr = string2jstring(env, " ");
    }

    jclass clsstring = env->FindClass("java/lang/String");
    jstring strencode = env->NewStringUTF("utf-8");
    jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
    jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode);
    jsize alen = env->GetArrayLength(barr);
    jbyte *ba = env->GetByteArrayElements(barr, JNI_FALSE);
    if (alen > 0) {
        rtn = (char *) malloc(alen + 1);
        memcpy(rtn, ba, alen);
        rtn[alen] = 0;
    }
    env->ReleaseByteArrayElements(barr, ba, 0);
    return rtn;
}

int mainEventFd;

int handlerCallBack(int ident, void *data) {

    YQ_HANDLER_LOGD("handlerCallBack-->ident:%d,data:%s  threadId:%ld", ident, data,
                    std::this_thread::get_id());
    sleep(1);
    mainHandler->sendMessage(ident, data);

    return 0;
}

int mainLooperCallBack(int ident, void *data) {
    uint64_t counter;
    TEMP_FAILURE_RETRY(read(mainEventFd, &counter, sizeof(uint64_t)));
    YQ_HANDLER_LOGD("mainLooperCallBack-->ident:%d,data:%s   threadId:%ld ", ident, data,
                    std::this_thread::get_id());
    sleep(1);

    return 1;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_heng_library_yhhandlerdemo_MainActivity_initHandler(JNIEnv *env, jobject thiz) {
    handler = YHHandler_create(false, handlerCallBack);
    mainHandler = YHHandler_create(true, mainLooperCallBack);
    char *data = "刚开始";
    handler->sendMessage(10002, data);
    mainHandler->sendMessage(10002, data);
    YQ_HANDLER_LOGD("initHandler  threadId:%ld", std::this_thread::get_id());

}

extern "C"
JNIEXPORT void JNICALL
Java_com_heng_library_yhhandlerdemo_MainActivity_quitHandler(JNIEnv *env, jobject thiz) {
    YQ_HANDLER_LOGD("quitHandler");
    if (handler) {
        YHHandler_destroy(handler);
        handler = nullptr;
    }
    if (mainHandler) {
        YHHandler_destroy(mainHandler);
        mainHandler = nullptr;
    }
}
uint64_t inc = 1;
extern "C"
JNIEXPORT void JNICALL
Java_com_heng_library_yhhandlerdemo_MainActivity_sendMessage(JNIEnv *env, jobject thiz,
                                                             jint what, jstring data) {

    if (handler) {
        YQ_HANDLER_LOGD("sendMessage-->%d   threadId:%ld", what, std::this_thread::get_id());
        handler->sendMessage(what, jstring2string(env, data));
    }
}